package dviz.visualSystem.impl;

import java.util.HashMap;
import com.jme.scene.Node;

import dviz.visualAspect.AnnotationHelper;
import dviz.visualAspect.MetaPropertyMap;
import dviz.visualAspect.MetaPropertyMap.InterpolateType;

/**
 * @author zxq071000
 */
public abstract class AnimationObject {
	/**
	 * @uml.property  name="renderNode"
	 * @uml.associationEnd  
	 */
	private RenderNode renderNode;
	/**
	 * @uml.property  name="mappedProperty"
	 */
	private HashMap<String, MetaPropertyMap> mappedProperty;

	// Don't detect change of property here anymore, it is done in
	// DeclarationTranslation system, inside the PropertyQuery implementation

	// private HashMap<String, AnimationObject> containList;
	// private HashMap<String, Object> cachedValue;

	private HashMap<String, ValueInterpolate> interpolator;

	public static class RenderNode extends Node {

	}

	public void renderUpdate(float fpt) {
	}

	public void update(float fpt) {
		for (ValueInterpolate v : interpolator.values()) {
			v.update(fpt);
		}
		renderUpdate(fpt);
	}

	public void setProperty(String property, Object value) {
		// AnnotationHelper.setter(this, property, value);
		ValueInterpolate interpolate = interpolator.get(property);
		if (interpolate == null) {
			MetaPropertyMap map = mappedProperty.get(property);
			if (map != null) {
				InterpolateType interpolateType = map.interpolateType;
				if (interpolateType == InterpolateType.INT_LAST_VALUE) {
					interpolate = new LastValueInterpolate();
				} else if (interpolateType == InterpolateType.INT_EXP_CONVERGE) {
					interpolate = new ExpInterpolate();
				} else if (interpolateType == InterpolateType.INT_LINEAR) {
					interpolate = new LinearInterpolate();
				} else
					assert (false);
			} else {
				interpolate = new LastValueInterpolate();
			}
			// throw new RuntimeException(
			// "AnimationObject->setProperty Unknown Interpolate Type:"
			// + interpolateType);
			if (map != null)
				interpolate
						.setProperty(mappedProperty.get(property).interpolateParameter);
			interpolator.put(property, interpolate);

		}
		interpolate.addValue(value);
	}

	// 2009-1-17: Before calling this function, at least one setProperty
	// function should be called
	public void updateProperty(String property) throws Exception {
		ValueInterpolate interpolate = interpolator.get(property);
		assert (interpolate != null);
//		if (interpolate != null) {
		if(interpolate==null)
			System.currentTimeMillis();
			Object value = interpolate.getValue();
			AnnotationHelper.setter(this, property, value);
	}

	/**
	 * @return
	 * @uml.property name="mappedProperty"
	 */
	public HashMap<String, MetaPropertyMap> getMappedProperty() {
		return mappedProperty;
	}

	// public boolean contains(String node) {
	// return containList.containsKey(node);
	// }
	//
	// public void cacheValue(String name, Object obj) {
	// if (cachedValue.containsKey(name))
	// cachedValue.remove(name);
	// cachedValue.put(name, obj);
	// }
	//
	// public Object getCached(String name) {
	// return cachedValue.get(name);
	// }
	//
	// public AnimationObject getContainedObject(String name) {
	// return containList.get(name);
	// }
	//
	// public void addContainNode(String name, AnimationObject ano) {
	// System.out.println("AnimationObject->AddContain() "+name);
	// if (contains(name)) {
	// getRenderNode().detachChild(ano.getRenderNode());
	// containList.remove(name);
	// }
	// containList.put(name, ano);
	// getRenderNode().attachChild(ano.getRenderNode());
	// }

	public AnimationObject(HashMap<String, Object> initVector) {
		renderNode = new RenderNode();
		mappedProperty = new HashMap<String, MetaPropertyMap>();
		interpolator = new HashMap<String, ValueInterpolate>();

		// renderNode.setName((String) initVector.get("nodeName"));
		for (String initKey : initVector.keySet()) {
			try {
				Object value = initVector.get(initKey);
				setProperty(initKey, value);
				updateProperty(initKey);
			} catch (Exception e) {
			}
		}
		// containList = new HashMap<String, AnimationObject>();
		// cachedValue = new HashMap<String, Object>();
	}

	public void setNodeName(String nodeName) {
		renderNode.setName(nodeName);
	}

	/**
	 * @return
	 * @uml.property name="renderNode"
	 */
	public final Node getRenderNode() {
		return renderNode;
	}

	// public final void setRenderNode(Node renderNode) {
	// this.renderNode = renderNode;
	// }

	// protected abstract Collection<String> objectPropertyList();

	public void addNode(HashMap<String, Object> arg) {
		try {
			AnimationObject animationObject = (AnimationObject) arg.values()
					.iterator().next();
			renderNode.attachChild(animationObject.getRenderNode());
			renderNode.updateModelBound();
		} catch (Exception e) {
			System.err.println(arg);
			e.printStackTrace();
			System.exit(0);
		}
	}

	public void removeNode(HashMap<String, Object> arg) {
		AnimationObject animationObject = (AnimationObject) arg.values()
				.iterator().next();
		renderNode.detachChild(animationObject.getRenderNode());
	}

}
